#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 2000001
#define inf 0x1fffffff
int n, m;
struct node
{
    int val, pos;
    node(int val = 0, int pos = 0) : val(val), pos(pos){};
};
node que[maxn];          //单调队列
int front = 1, tail = 0; //队头1队尾0,表示队为空,这里因为数据原因:每个数最多处于队列的一个位置,所以不需要使用循环队列的技巧
int arr[maxn];
int main()
{
    cin >> n >> m;
    for (int i = 1, tmp; i <= n; ++i)
    {
        scanf("%d", &arr[i]);
    }
    for (int i = 1; i <= n; ++i)
    {
        printf("%d\n", que[front].val);                  //队头元素最小,也就是区间[max(i-m,0),max(0,i-1)]的最小值
        while (front <= tail && que[front].pos + m <= i) //此时的队头元素已经不在[max(i-m,0),max(0,i-1)]的范围内了
        {
            //这一步意味着我们将队头元素出队了,并且直到发现一个新的队头元素在区间内,又有队列的单调特征保证现在的队头元素是最小的
            front++;
        }
        while (front <= tail && que[tail].val >= arr[i]) //首先我们要将新元素arr[i]入队,但是如果arr[i]已经是最小元素了,那么队列中的所有元素都可以丢掉了
        {
            tail--; //比arr[i]还要大的元素可以都丢掉了,因为它们不仅比arr[i]大,还处于区间的更左边,总会在arr[i]之前被移出队列
        }
        que[++tail] = node(arr[i], i); //入队
    }
    return 0;
}